Skip to content

Fix crash in fillNullTerminatedWideStringBuffer()#304

Open
broken-circle wants to merge 1 commit into
swiftlang:mainfrom
broken-circle:fillStringBuffer-crash
Open

Fix crash in fillNullTerminatedWideStringBuffer()#304
broken-circle wants to merge 1 commit into
swiftlang:mainfrom
broken-circle:fillStringBuffer-crash

Conversation

@broken-circle

@broken-circle broken-circle commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

The function passed a typed-throwing closure to withUnsafeTemporaryAllocation(of:capacity:_:), which is rethrows. Bridging the typed throw into rethrows crashes under release optimization on the Swift 6.2.x Windows toolchain (debug builds and nightly-main are unaffected).

This PR restructures it so the allocation closure no longer throws. Instead, it returns a result enum, and the enclosing loop throws or grows the buffer accordingly. This drops the typed-throws-into-rethrows bridge, which in turn drops the #if swift(>=6.3) workaround guarding the same path, and allows body to be non-throwing, since no caller throws from it.

The original implementation used an assert(); this was the only use in the package, and I removed it based on a review comment on #280 explaining that Subprocess tries not to use assert().

Found this when running CI for #261. Windows (6.2 - windows-2022) crashed, while all other CI including Windows (nightly-main - windows-2022) passed.

On main this function is reached only through paths that run without crashing in release CI. #261 adds a new caller, currentWorkingDirectory(), invoked from the spawn path in Configuration.run(), which is where the crash occurs.

The function passed a typed-throwing closure to
`withUnsafeTemporaryAllocation()`, whose closure parameter is `rethrows`.
Bridging the typed throw into `rethrows` miscompiles under release
optimization on the Swift 6.2.x Windows toolchain and crashes; debug
builds and nightly-main are unaffected.

Restructure so the allocation closure no longer throws. Instead, it
returns a result enum, and the enclosing loop throws or grows the buffer
accordingly. This drops the typed-throws-into-`rethrows` bridge, which
in turn drops the `#if swift(>=6.3)` workaround guarding the same path
and allows `body` to be non-throwing, since no caller throws from it.
Also remove `assert()`; the package avoids its use everwhere. Behavior
is otherwise unchanged.
@broken-circle broken-circle requested a review from iCharlesHu as a code owner June 8, 2026 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant